﻿# coding=UTF-8
from appengine_django.models import BaseModel
from google.appengine.ext import db
#from django.contrib.contenttypes.models import ContentType  
#from django.contrib.contenttypes import generic  
from django.db.models.signals import post_save,pre_delete,post_delete
import logging
from django.db.models import signals,permalink
from google.appengine.api import users
from django.db import models
from django.utils.encoding import force_unicode,smart_str
from django.core.urlresolvers import reverse
#Base Model for signals:pre_save, post_save          
class SignalsBaseModel(BaseModel):
    def put(self,created=False):  
        created=not self.is_saved()      
        signals.pre_save.send(sender=self.__class__, instance=self) 
        key=super(SignalsBaseModel,self).put()
        signals.post_save.send(sender=self.__class__, instance=self,created=created)        
        return key 
    #override put method in case signals not sent 
    #when using google.appengine.ext.db import djangoforms.save(commit=True)

    save=put

    def delete(self):
        signals.pre_delete.send(sender=self.__class__, instance=self)
        super(SignalsBaseModel,self).delete()
        signals.post_delete.send(sender=self.__class__, instance=self)
        
class SysInfo(BaseModel):
    post_count=db.IntegerProperty(default=0)
    comment_count=db.IntegerProperty(default=0)
    

class Archive(BaseModel):
    monthyear = db.StringProperty(multiline=False)    
    weblogcount = db.IntegerProperty(default=0)
    date = db.DateTimeProperty(auto_now_add=True)

class Tag(BaseModel):
    name = db.StringProperty(multiline=False)
    slug=db.StringProperty(multiline=False)
    entrycount = db.IntegerProperty(default=0)
    valid = db.BooleanProperty(default = True)
    def __unicode__(self):
        return self.name

class Category(BaseModel):
    name=db.StringProperty(multiline=False)
    slug=db.StringProperty(multiline=False)
    entrycount = db.IntegerProperty(default=0)    
    def __unicode__(self):
        return self.name

class Post(SignalsBaseModel):
    title = db.StringProperty(required=True)
    content = db.TextProperty(required=True)
    date = db.DateTimeProperty(auto_now_add=True)
    author = db.UserProperty()
    authorEmail = db.EmailProperty(required=True)
    category=db.ReferenceProperty(Category)
    categories = db.ListProperty(db.Key)
    tags = db.ListProperty(db.Key)
    slug = db.StringProperty()
    lastCommentedDate = db.DateTimeProperty()
    commentcount = db.IntegerProperty(default=0)
    visitcount = db.IntegerProperty(default=0)
    lastModifiedDate = db.DateTimeProperty()
    lastModifiedBy = db.UserProperty()    
    entryType = db.StringProperty(required=True,multiline=False,default='post',choices=['post','page'])
    isPublished = db.BooleanProperty(default=False)

    def delete(self):
        comment = self.comment_set.get()
        if comment:
            comment.delete()
        super(Post, self).delete()
        
    def __unicode__(self):
        return '%s adds a post: [%s] at %s'%(self.author,self.title,self.date.strftime('%A, %d. %B %Y %I:%M%p'))
        
    @models.permalink
    def get_absolute_url(self):
        return ('blog.views.view_post', [smart_str(self.key().id())])
    
    
    def get_permalink(self):
        if not self.slug:
            return reverse('blog.views.view_post', args=[smart_str(self.key().id())])

        try:
            return reverse('view_post_perma',urlconf=None, args=None ,kwargs={
            'year': self.date.year,
            'month': str(self.date.month).zfill(2),
            'day': str(self.date.day).zfill(2),
            'slug': self.slug})  
        except:
            try:
                return reverse('view_post_perma',urlconf=None, args=None ,kwargs={
                'year': self.date.year,
                'month': str(self.date.month).zfill(2),
                'slug': self.slug})  
            except:
                try:
                    return reverse('view_post_perma',urlconf=None, args=None ,kwargs={
                    'slug': self.slug})  
                except:
                    return reverse('blog.views.view_post', args=[smart_str(self.key().id())])
        
    @property
    def next(self):     
        return Post.gql('WHERE date > :1 ORDER BY date',self.date).fetch(1)

    @property
    def prev(self):
        return Post.gql('WHERE date < :1 ORDER BY date DESC',self.date).fetch(1)

        
class Comment(SignalsBaseModel):
    post = db.ReferenceProperty(Post)
    user = db.StringProperty(required=True)
    date = db.DateTimeProperty(auto_now_add=True)
    author = db.UserProperty()
    authorEmail = db.EmailProperty(required=True)
    authorWebsite = db.StringProperty()
    userIp = db.StringProperty()
    content = db.TextProperty(required=True)
    lastModifiedDate = db.DateTimeProperty()
    lastModifiedBy = db.UserProperty()

    def __unicode__(self):
        return '%s adds a comment on Post: [%s] at %s'%(self.user,self.post.title,self.date.strftime('%A, %d. %B %Y %I:%M%p'))

#    def save(self):
#        super(Comment, self).put()
#        if self.post :
#            self.post.lastCommentedDate = self.date
#            self.post.commentcount += 1
#            self.post.put()

class Event(BaseModel):  
    event = db.ReferenceProperty()
    created = db.DateTimeProperty(auto_now_add=True)
    
      
#def callback_on_pre_save(sender,**kwargs):  
#    instance = kwargs['instance']
#    event = Event(user=users.get_current_user(),event = instance)  
#    event.put()  

def sync_tag_entrycount_when_add_post(sender,**kwargs):
    post = kwargs['instance']
    if kwargs['created']:
        tags=post.tags                
        if tags:            
            for key in tags : 
                tag=db.get(key)      
                tag.entrycount+=1
                tag.put()
#                logging.info('in sync add tag counts, tag_count=%s'%tag.entrycount)
    

def sync_tag_entrycount_when_delete_post(sender,**kwargs):
    post = kwargs['instance']    
    tags=db.get(post.tags)
    if tags:    
        for tag in tags :       
            tag.entrycount-=1
            tag.put()

def sync_category_entrycount_when_add_post(sender,**kwargs):
    post = kwargs['instance']
    if kwargs['created']:
        category=post.category
        if category:
            category.entrycount+=1
            category.put()
        categories=db.get(post.categories)
        if categories:
            for cat in categories :       
                cat.entrycount+=1
                cat.put()
    

        
def sync_catagory_entrycount_when_delete_post(sender,**kwargs):
    post = kwargs['instance']    
    category=post.category
    if category:
        category.entrycount-=1
        category.put()
    categories=db.get(post.categories)
    if categories:
        for cat in categories :       
            cat.entrycount-=1
            cat.put()
    
def sync_post_comment_entrycount_when_add_comment(sender,**kwargs):
    comment = kwargs['instance']
    if kwargs['created']:
        post=comment.post
        if post:
            post.lastCommentedDate = comment.date
            post.commentcount += 1
            post.put()
    

def sync_post_comment_entrycount_when_delete_comment(sender,**kwargs):
    comment = kwargs['instance']
    post=comment.post
    if post:
        post.commentcount -= 1
        post.put()

def callback_on_post_save(sender,**kwargs):  
    instance = kwargs['instance']
    if kwargs['created']:  
#        logging.info('[event]post_save: %s'%instance)        
        event = Event(user=users.get_current_user(),event = instance)  
        event.put()  
    
def callback_on_pre_delete(sender,**kwargs):  
    instance = kwargs['instance']
    event = Event.all().filter("event =", instance).get()
    if event:
#        logging.info('delete an event:%s'%event.event)
        event.delete()
        

signals.post_save.connect(sync_post_comment_entrycount_when_add_comment, sender=Comment)
signals.pre_delete.connect(sync_post_comment_entrycount_when_delete_comment, sender=Comment)

signals.post_save.connect(sync_tag_entrycount_when_add_post, sender=Post)
signals.pre_delete.connect(sync_tag_entrycount_when_delete_post, sender=Post)
signals.post_save.connect(sync_category_entrycount_when_add_post, sender=Post)
signals.pre_delete.connect(sync_catagory_entrycount_when_delete_post, sender=Post)
#signals.pre_save.connect(callback_on_pre_save, sender=None)
signals.post_save.connect(callback_on_post_save, sender=Comment)
signals.post_save.connect(callback_on_post_save, sender=Post)
signals.pre_delete.connect(callback_on_pre_delete, sender=None)
